/**
* @file ScanBuffer.h ScanBuffer Definitionen
*
*/
#ifdef WIN32
	#include <io.h>
#else
	#include <fcntl.h>
	#include <sys/types.h>
	#include <unistd.h>
#endif

#ifndef _SCAN_BUFFER_RING_INCLUDE_
#define _SCAN_BUFFER_RING_INCLUDE_


/**
* Exception Oberklasse.
* Muss von allen Exceptionklassen für einen ScanBuffer erweitert werden.
*/
class BufferException {
	char* msg;
public:	
	BufferException(char* msg) {
		this->msg = msg;
	}
	
	virtual char* getMessage() {
		return this->msg;
	}

};

/**
* Exception für EA-Fehler.
* Werden geworfen, falls der Buffer die angebenen Datei nicht richtig lesen kann.
*/
class ScanBufferIOException : public BufferException {
public:
	ScanBufferIOException(char* msg) : BufferException(msg) {}
};


/**
* ScanBuffer Interface.
* Ein ScanBuffer muss dieses Interface implementieren.
*/
class ScanBuffer {
public:	
	/**
	* Returns the next char of the buffer.
	* \return Next char off the buffer.
	*/
	virtual char getNextChar() = 0;
	
	/**
	 * @return Number of the current line.
	 */
	virtual unsigned int getLine() = 0;
	
	/**
	 * @return Number of the current column.
	 */
	virtual unsigned int getColumn() = 0;
	
	/**
	 * Rewinds the buffer with 1 and set the used chars for deleting.
	 */
	virtual void unGetChar() = 0;
	
	
	/**
	 * Opens the file to read
	 */
	virtual void openFile(char* filename) = 0;
	virtual ~ScanBuffer() {};
};

/**
* ScanBufferRing implementiert ScanBuffer. 
* Basiert auf dem Ringpuffer-Prinzip.
*/
class ScanBufferRing : public ScanBuffer {

	char** buffer; //!< Ein zweidimensionales Array für den Ring.
	
	/*
	 * Größe der Blöcke, Zeilen- und Spaltenzähler, ..., Position des nächsten Zeichens im Buffer,
	 * Index für den derzeitigen Block
	 */
	int blockSize, lineCount, columnCount, eofCounter, charPos, blockPos, oldColumnCount;
	
	
	bool override[2]; //!< Gibt an, ob ein Block überschrieben werden darf.
	
	 
	int fd; //!< File Descriptor
	
	/**
	* Reads a new Block from the file into the buffer-array.
	*
	* \param index Defines the index of the ringbuffer.
	*/
	void readBlock(int index);

public:
	/**
	* Constructor.
	* \param blockSize Size of each block.
	*/
	ScanBufferRing(int blockSize);
	
	/**
	* Destructor.
	*/
	~ScanBufferRing();

	/**
	* Opens the file to read
	*/
	void openFile(char* filename);	
	
	/**
	* Returns the next char of the buffer.
	* \return Next char off the buffer.
	*/
	char getNextChar();
	
	/**
	* Rewinds the position pointer with a definable amount of steps.
	* \param count Amount of steps
	*/
	void rewind(int count);
	
	/**
	* Set the amount of chars, which from now on are alowed to get deleted.
	* \param count Amount of chars.
	*/
	void setProcessedChars(int count);
	
	/**
	 * Rewinds the buffer with 1 and set the used chars for deleting.
	 */
	void unGetChar();
	
	/**
	* Returns the current lexem.
	* \return The current lexem.
	*/
	char* getCurrentLexem();

	unsigned int getLine();
	unsigned int getColumn();
};

#endif
